home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / Z80 emulator / 68K version / Z80.doc < prev    next >
Encoding:
Text File  |  1995-11-19  |  11.1 KB  |  201 lines  |  [TEXT/ttxt]

  1.  
  2.         Z80.doc                                                 18.Feb.95 KIO !
  3.     
  4.         Documentation for the 68020 based Z80 emulator
  5.  
  6.         note: a lot of things have changed since i write this doc. don't be too upset... !
  7.  
  8. Legal note
  9.  
  10. Z80 engine 68020 based
  11. Copyright (C) 1994-1995
  12. Günter Woigk
  13. Nürnberger Str. 79
  14. 91052 Erlangen
  15. Germany
  16. email: kio@vanilla.nbg.sub.org
  17.     
  18. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of  the License, or (at your option) any later version.
  19.  
  20. This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See theGNU General Public License for more details.
  21.  
  22. You should have received a copy of the GNU General Public Licensealong with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  23.  
  24.  
  25. General
  26.  
  27. The file "z80.c" is the C/assembler source for an emulator of the Zilog Z80 CPU. It is designed for high speed and ease of use.
  28.  
  29. At the moment of writing this emulator supports:
  30.  
  31. • all legal instructions except 
  32.    INI, IND, INIR, INDR, OUTI, OUTD, OTIR, OTDR
  33. • most illegal instructions
  34. • normal interrupts in all three modes except multi-byte instructions in IM0
  35. • NMI, trace mode and watchdog
  36. • 16 bit i/o addresses
  37.  
  38. It does not exactly emulate:
  39.  
  40. • DAA instruction and it's corresponding bits.
  41. • exact timing of Z80 opcodes
  42. • exact incrementation of the F register
  43. • some undocumented opcode side effects
  44. • write protection for ROMs
  45.  
  46. The emulator is extremely fast. On a 68030/32 it should have the overall performance of a 4 MHz Z80. (neglecting the time an emulator will spend updating a screen)
  47.  
  48.  
  49. Procedures
  50.  
  51. OSErr Init_Z80()  allocates and initializes a 64 kByte RAM/ROM core. Actually 128 kByte of RAM are allocated, for the emulator always locates the Z80 RAM at a multiple of 0x10000. It also resets the Z80 CPU and initializes it's register structure and calculates all required conversion tables. And it sets the byte, which  the Z80 CPU reads at it's interrupt acknowledge cycle from the data bus to 0xFF, which in most cases is the byte it would read in a real system. On success Init_Z80()  returns 0x00; if it could not allocate memory for the Z80 core, it returns a non-zero value.
  52.  
  53. short Z80()  is the routine, which actually interprets and emulates Z80 instructions. On entry, it reads all registers from the structure zreg  and on return it writes them back to zreg. The result value indicates the reason why Z80()  returned.
  54.  
  55.  
  56. The zreg  structure
  57.  
  58. The type for this structure is defined in "Z80.h" and is called regs. Inside regs  a union named pair  is used to describe registers which may be used as pointers.
  59.  
  60. union pair    {
  61.         unsigned char *ptr;
  62.         struct { unsigned short corebase, reg; } rr;
  63.         struct { unsigned short corebase; unsigned char hi, lo; } r;
  64.         };
  65.  
  66. pair.ptr  is used to address bytes inside the Z80 core. The high word of this address is initialized by InitZ80()  and must not be changed. In general: don't use pair.ptr.
  67.  
  68. pair.rr.corebase  or pair.r.corebase  is initialized by InitZ80()  as mentioned above and must not be modified.
  69.  
  70. pair.rr.reg  may be used to read or write a register pair.
  71.  
  72. pair.r.hi  and pair.r.lo  may be used to read or write a single register.
  73.  
  74. struct regs {
  75.         pair     BC, DE, HL, IX, IY, IP, RP ;
  76.         Short     BC2, DE2, HL2 ;
  77.         Char        AA2, A2, aa, A ;
  78.         Char        FF2, F2, ff, F ;
  79.         Char        I, irptcmd ;            
  80.         Char        IFF1, IFF2 ;        
  81.         Char        WUFF ;
  82.         Char        R ;
  83.         Char        IM ;        
  84.         };
  85.  
  86. zreg.BC  to zreg.RP  are the most frequently used register pairs. 
  87.  
  88. zreg.BC2  to zreg.HL2  are the exchange register pairs used in the EXX instruction. 
  89.  
  90. zreg.AA2, zreg.FF2, zreg.aa  and zreg.ff  are initialized to 0x00 by Init_Z80()  and must not be changed. 
  91.  
  92. zreg.A  and zreg.F  are the AF register pair, zreg.A2  and zreg.F2  are their exchange register pair used in EX AF,AF'. Flagbits are stored according to the mc68000 flag register, not as in the Z80 flag register! 
  93.  
  94. zreg.I  is the I register; zreg.irptcmd  is the byte which the Z80 CPU reads in interrupt acknowledge cycle from data bus. This byte is preset to 0xff by Init_Z80()  and may be set to any desired value before signaling an interrupt.
  95.  
  96. zreg.IFF1  and zreg.IFF2  represent the interrupt enable flag and it's temporaryly saved value during NMI processing.
  97.  
  98. zreg.WUFF  contains 4 bits which may be set from an implementation depending interrupt routine. Their bitmask and meaning is as follows:
  99.  
  100.     0x80    trace flag: forces Z80()  to return after every statement 
  101.                 or after processing an interrupt or NMI.
  102.     0x40    watchdog interrupt: forces Z80()  to return immediately.
  103.     0x20    NMI: Z80() processes an NMI cycle and resets the request.
  104.     0x10    not used; must be 0
  105.     0x0F    Normal interrupt: Z80() processes an interrupt cycle reading 
  106.                 zreg.irptcmd  from the bus and decrements the request counter by 1.
  107.     
  108. zreg.R  represents the refresh counter of the Z80 CPU. Actually, it is incremented by 7 every time it is read by the LD A,R instruction thus implementing a minimum emulation.
  109.  
  110. zreg.IM  stores the interrupt mode, the Z80 CPU actually runs in. 
  111.  
  112.  
  113. Return values of Z80()
  114.  
  115. 0    Watchdog exception. May be used by a watchdog timer. The watchdog flag in zreg.WUFF  should be cleared befor Z80()  is called again. Mac Spectacle uses watchdog interrupts to poll Mac OS events and update the ZX Spectrum screen.
  116.  
  117. 1    Trace exception. The Z80 CPU runs in trace mode and after every instruction or after processing an interrupt or NMI cycle, Z80()  returns to the calling application. Note, that your application should not generate interrupts when you trace a routine interactively.
  118.  
  119. 2    A not implemented instruction was executed. zreg.IP  points to the first byte of the incriminated opcode. You should abort further execution of this Z80 program, for it has crashed, either due to an error in the emulator or due to an error in the Z80 target application itself.
  120.  
  121. 3    The Z80 instruction HALT was executed. The application should poll Mac OS events until an NMI or normal interrupt occurs. If interrupts are disabled, you must only wait for NMI's. Before calling Z80()  again, you must check for trace mode and call your trace mode handler just as it would be called, if a trace exception occured.
  122.  
  123. 4    The Z80 instruction RST 0 was executed. This opcode is trapped as a possibility to call native 68000/PPC code to perform some system routines quicker than they were performed emulating the Z80 code. To decide which system function must be emulated, check the current PC in zreg.IP , which points to the next instruction. Z80()  does nothing except returning with code 4, when a RST 0 is executed. If you want to make the RST 0 opcode just do what it does on a real Z80, push the PC on the stack and set the PC to 0x0000. Before calling Z80()  again, you must check for trace mode and call your trace mode handler just as it would be called, if a trace exception occured.
  124.  
  125. 5   The emulator trapped an instruction which attempted to write to the  ROM. This error only occurs, if the associated compiler option were enabled. The address of this instruction is stored in zreg.IP.  Abort further execution of the Z80 target application.
  126.  
  127. Note, that the zreg.IP  normally points to the next instruction, when Z80()  returns except for return code 5 (ROM write attempt) and 2 (not implemented opcode), where it points to the faulty instruction.
  128.  
  129.  
  130. Input and output instructions
  131.  
  132. Every input instruction results in Z80()  calling Char Do_Input(register Short address)  and you must provide this function somewhere in your application. 
  133.  
  134. Every output instruction will call Do_Output(register Short address, register Char value)  which must be provided in your application too.
  135.  
  136. Block i/o commands are not supported in this version of Z80().
  137.  
  138.  
  139. Debugger info calls
  140.  
  141. When compiling "z80.c" you can set a lot of switches in "z80.options" which will result in calls to Do_Info(long PC) . The argument to Do_Info()  is the PC of the instruction which was trapped. Don't use zreg  do determine Z80 registers and don't write to zreg  to modify Z80 registers. Some registers in zreg  are valid, others are not. Actually, PC, SP, A, A', F and F' are kept in mc68020 registers and are not valid in zreg, but this may not be true in the next version of Z80().  These calls are for information purpose only and should take as little time as possible. For a complete list of all instructions which have optional switches to call Do_Info()  refer to "z80.options".
  142.  
  143.  
  144. Write protection for ROM address space
  145.  
  146. If you set either ROM_protection  or ROM_exception  in "z80.options", compiling "z80.c" will include code to check destination addresses of write instructions to prevent your ROM from beeing overwritten. The ROM address space is defined by ROM_start  and ROM_end  in "z80.options". In the actual version of Z80()  the following instructions are checked:
  147.   ld (addr),n
  148.   ld (addr),nn
  149.   inc (addr)
  150.   dec (addr)
  151.   set (addr)
  152.   res (addr)
  153. The following instructions are not checked:
  154.   block moves
  155.   stack operations
  156.  
  157. It is still possible to overwrite the first byte of the ROM with a ld(addr),nn instruction.
  158.  
  159.  
  160. Which Functions must be provided by an application which uses Z80()  ?
  161.  
  162. extern    Do_Output          ( register Short addr, register Char n )   Handle OUT instructions
  163. Char         Do_Input            ( register Short addr )                                     Handle IN instruction
  164. extern    Do_Info              ( Char *ip )                                                          Called if info_XXXX==on
  165. extern    Do_1st_Loc     ( Char *ip )                                                         Required if pc_firstuse==on
  166. extern    Do_1st_Instr ( Char *ip )                                                        Required if cmd_firstuse==on
  167.  
  168.  
  169. Trace Mode Cave At's
  170.  
  171. • Check for trace mode after performing a HALT or RST 0 instruction and call your trace handler if necessary.
  172. • You should switch off your interrupt generation when tracing Z80 code. 
  173. • When EI is performed in trace mode, make shure the next instruction can be executed without beeing interrupted by a normal interrupt, if you have not disabled interrupt generation.
  174. • Normally, the instruction addressed by zreg.IP  is executed next. Evaluate Do_Info()  calls to see, whether an NMI or (if not switched off) a normal interrupt is processed instead.
  175.  
  176.  
  177. Standard Use of the Z80 Engine
  178.  
  179. Call Init_Z80()  to initialize the engine and set the registers to reset condition. After that copy a ROM image into the CORE, set up an interrupt generating routine which triggers the corresponding bits in zreg.WUFF  and at last call Z80()  in a loop. Every time Z80()  returns, examine it's result code and do appropriate action; e.g. wait for next interrupt on a HALT instruction or call your replacement routine for a RST 0 instruction.
  180.  
  181. Use watchdog interrupts to copy a memory mapped video display to a Macintosh window and to poll Mac OS events. Store Mac OS events in some kind of data and evaluate this data in your Do_Input()  and Do_Output()  routines. 
  182.  
  183.  
  184.  
  185.  
  186.  
  187.  
  188.  
  189.  
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200.  
  201.